package com.stars.module.privilege.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.stars.base.constants.CommonNumberConstants;
import com.stars.base.constants.SystemConstants;
import com.stars.base.entity.CommonDTO;
import com.stars.base.entity.TreeNode;
import com.stars.module.grant.service.StarGrantService;
import com.stars.module.privilege.entity.StarPrivilege;
import com.stars.module.privilege.mapper.StarPrivilegeMapper;
import com.stars.module.privilege.service.StarPrivilegeService;
import com.stars.util.common.DevelopKit;
import com.stars.util.tree.TreeNodeUtil;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.List;

/**
 * @author : Rocks
 * @version : 1.0
 * @date : 2022/11/30 14:02
 * @description : 权限相关服务实现类
 */
@Service
public class StarPrivilegeServiceImpl implements StarPrivilegeService {

    private final StarPrivilegeMapper mapper;
    private final StarGrantService grantService;

    public StarPrivilegeServiceImpl(StarPrivilegeMapper mapper, StarGrantService grantService) {
        this.mapper = mapper;
        this.grantService = grantService;
    }

    @Override
    public boolean saveOrUpdatePrivilege(StarPrivilege entity) {

        String privilegeId = entity.getId();

        if (StringUtils.hasLength(privilegeId)) {
            return mapper.updateById(entity) > 0;
        }

        entity.setRowStatus(1);
        entity.setId(DevelopKit.generateUUID());
        //处理step
        if (StringUtils.hasLength(entity.getFid())) {

            QueryWrapper<StarPrivilege> query = new QueryWrapper<>();
            query.lambda().eq(StarPrivilege::getFid, entity.getFid());
            query.select("MAX(STEP) AS STEP");

            StarPrivilege maxStepEntity = mapper.selectOne(query);
            if (maxStepEntity == null) {

                StarPrivilege fPrivilege = mapper.selectById(entity.getFid());
                if (fPrivilege == null) {
                    entity.setStep(SystemConstants.STEP_ROOT);
                } else {
                    entity.setStep(fPrivilege.getStep() + SystemConstants.STEP_NEW);
                }
            } else {
                long maxStep = Long.parseLong(maxStepEntity.getStep()) + 1;
                entity.setStep(String.valueOf(maxStep));
            }
        }

        return mapper.insert(entity) > 0;
    }

    @Override
    public boolean removePrivilege(String id) {

        StarPrivilege entity = mapper.selectById(id);

        LambdaQueryWrapper<StarPrivilege> query = new LambdaQueryWrapper<>();
        query.likeRight(StarPrivilege::getStep, entity.getStep());

        return mapper.delete(query) > 0;
    }

    @Override
    public JSONArray loadTree() {

        LambdaQueryWrapper<StarPrivilege> query = new LambdaQueryWrapper<>();

        query.orderByAsc(StarPrivilege::getShowOrder);

        JSONArray array = new JSONArray();

        List<StarPrivilege> list = mapper.selectList(query);

        List<TreeNode> treeNodes = new ArrayList<>();

        for (StarPrivilege privilege : list) {
            TreeNode node = new TreeNode();

            node.setValue(privilege.getId());
            node.setLabel(privilege.getPrivilegeName());
            node.setpId(privilege.getFid());

            JSONObject attr = new JSONObject();
            attr.put("type", privilege.getDirectory());

            node.setAttr(attr);

            treeNodes.add(node);
        }

        TreeNode root = new TreeNode(CommonNumberConstants.ZERO_STR, "权限管理", CommonNumberConstants.MINUS_ONE_STR);

        array.add(TreeNodeUtil.merge(root, treeNodes).toJSON());

        return array;
    }

    @Override
    public JSONObject loadDataListByFid(CommonDTO dto) {

        Page<StarPrivilege> page = Page.of(dto.getCurrent(), dto.getPageSize());

        LambdaQueryWrapper<StarPrivilege> query = new LambdaQueryWrapper<>();

        query.eq(StarPrivilege::getFid, dto.getFid()).like(StarPrivilege::getPrivilegeName, dto.getSearch());

        query.orderByAsc(StarPrivilege::getShowOrder);

        Page<StarPrivilege> privilegePage = mapper.selectPage(page, query);

        JSONObject result = new JSONObject();

        result.put("list", privilegePage.getRecords());
        result.put("total", privilegePage.getTotal());

        return result;
    }

    @Override
    public StarPrivilege loadPrivilegeById(String id) {
        return mapper.selectById(id);
    }

    @Override
    public Object getMaxIndex(String fid) {

        QueryWrapper<StarPrivilege> query = new QueryWrapper<>();

        query.lambda().eq(StarPrivilege::getFid, fid);
        query.select("MAX(SHOWORDER) AS SHOWORDER");

        StarPrivilege entity = mapper.selectOne(query);

        return entity == null ? 0 : entity.getShowOrder();
    }

    @Override
    public String loadUserPrivileges(String userId) {
        return grantService.loadUserPrivileges(userId);
    }

    @Override
    public JSONArray loadSelectTree() {

        LambdaQueryWrapper<StarPrivilege> query = new LambdaQueryWrapper<>();

        query.orderByAsc(StarPrivilege::getShowOrder);

        JSONArray array = new JSONArray();

        List<StarPrivilege> list = mapper.selectList(query);

        List<TreeNode> treeNodes = new ArrayList<>();

        for (StarPrivilege privilege : list) {
            TreeNode node = new TreeNode();

            node.setValue(privilege.getId());
            node.setLabel(privilege.getPrivilegeName());
            node.setpId(privilege.getFid());

            node.setDisabled(CommonNumberConstants.ONE_STR.equals(privilege.getDirectory()));

            treeNodes.add(node);
        }

        TreeNode root = new TreeNode(CommonNumberConstants.ZERO_STR, "权限管理", CommonNumberConstants.MINUS_ONE_STR);

        array.add(TreeNodeUtil.merge(root, treeNodes).toJSON());

        return array;
    }


}
